package com.itheima.mobili;

import cn.hutool.core.date.DateUtil;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.itheima.pojo.Result;
import com.itheima.service.OrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @version V1.0
 * @author: yongjichu
 * @date: 2020/2/5 18:32
 * @description:
 */
@RestController
@RequestMapping("/pay")
public class PayController {
    @Reference
    private OrderService orderService;
    Logger log = LoggerFactory.getLogger(PayController.class);
    //支付宝服务器地址
    String SERVERURL = "https://openapi.alipaydev.com/gateway.do";
    //商户appid
    String APP_ID = "2016102000727703";
    //商户私钥
    String APP_PRIVATE_KEY ="MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDEvMeE4icumBA4iClqMnAP7rAT1WJcWPzDq73OGky5GSFYsIEuxaNqhZOhv7fDD6K4OZCQ9dzWyp6BwY61lnPhkshO3fXhp9dxEaWfyYFFRYftE2oeeZ46mYpDt8B/jYvxDuTjjDl9arXFzwVbVhq4OCnmA1YT5ARkB3TC1znAoyl7YPtWAHXq5pqbnL32JwiNq8R4FaMBpPc5m8lyIPpt0wuWDnMF7JP7zyA1y1kuRtRTmUjBjy2kSYWSbM1ugaASU7k7oDdYEZ09SFR0TjgYN1V58ppYVwfatGO3LGgNpnajLZjYQShWnKyUuUxHzfxteDwj1l+UYOWBvN6tB1aJAgMBAAECggEBAIWLN0vmT357ThdxpdsmXZcTCIaOA/R3mywfOfnbNFU4z7/qH+Zl1eWKwom7H7vSszumJ5GessdCRpIBlyN/+y0Ve869MBh62+0uc2ShXZRt/DRbR19kYpmYe5g39P0gUevRlmE3YBbYBoc9XX+AVSbTSO2POjDKSIi13vYbLmKprX2dZRmyfoM5GXnGmY1HUExiV0fbqq4paXx+LWYiL4jFyhvqiugFTdJ4+PSl1vdiTut2+YWPVeord5TJlotz3+GfUZhYs2XtksCUmN9UtI2TqI11TPn0Fi+v0Uq359DKQXHbsINqq6W0XFmq6mZcLQWBjJXtDdol0+Y9uS3PuJkCgYEA7Ddw2YXrfh2T+supV1QQUjR/dQSrjtK88uYwps7XTks0A9vmrLbS2s1Q659jGA/+YX1WuuSaqzluJRGrdeA0DqRPKqWYG++Nyg3Kj5my36rL77gyIOBdNm92xU5xsqJLMkSYieCAzLOlbECfI/n4zcXOQ1Rq6joSAD6RVVlSbasCgYEA1TbkmIBWM32WxyhIpGdo3iBBl8YUbIpne9adP0Vi5BxUXVuLsXCCtiftm0xURsv8D10pDjYIHNnpw9OC7mbHIettVIA4TylkhwQ4ZPiLdp1R25T+Rs8s3FesytrNUOe5lXxla2pF5L52GxWfbCqrMEeR7bflnmY42udXC3EM0JsCgYB0KP9RuM2JgzoWBrkLvMcZ5b8X6GgFIBTSzef235h5Y/n8O9M/89fUyUqV1BeC6bqKbnyMA4cb1G4ZxIqwuMRgvuQ/cJdQhYkQZ5/I5ihUXUVUaRwdlre/4Shi9qRq1+xql9j7VG+COoWKqmyX4IE9j5xS99xruorHm/0UH4ytaQKBgQCmJSFbCN6jPyFITkbU/dQFC4OxfmQZ9HwRTzq3vB0EfmLrYNPpUDA7O7/2/TLK/FeNrV25ujb2LITx2Rc1KRfRgcBvUX8PiMTSRWKgo+EhbBQGlQLUMMrXZOa8KGZHvlqqdwYc/vI5/oTQNDhHtLQzagH4CQ5AMY3qXs1AmDaRMwKBgQCfnS1OArwv9DAqSkOMclRYlizH4onnCnL8Fn+16KUAiv6qDwO3jjJdWi5JU54QTl/1LUnTiJIaJ6m0AMwy0m4M4uR4HYkD6vB0Z11c5b0j9Ni6FmJVZQSY87hQbD1UqvQTiZcyhGK//+7bGphPqDr7RA135F6JeI6fispifVjYwA==";
    String CHARSET = "UTF-8";
    //支付宝公钥
    String ALIPAY_PUBLIC_KEY ="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm8pRpAjv/T5LIjWZHnNJrGv+rg7ySYDuH7Pn9wMQKwodGVuMV0F+E789MSFfaKUsIgkrtQfTbKKYjcWkquoDI0cNlfaMmGk7R0Bo4Lajzq6HMYDUJrIPagWj63tK2jwwfJSijJM70+k5Huk0Erkvche81ge0q0Vr22BVGdY6GjpGQhQPxL56Je7N3DKh+F/62nsdfwVGpj3SaktiYx9W07HUwtbXawCWj6lboTCGUi719Sx2dCU33fhWYiwhNhs2Onf6hh9TumaZ2Hi4wYYPNxrMd9O23SRLfHbBcpMDC+f1fM+YebjlfRMmxVFktyV5ckiNTyqZoOleSIlTT9Ir+wIDAQAB";

    /**
     * 构造支付请求
     * @param request
     * @param response
     * @param orderId
     */
    @RequestMapping("/alipay")
    public void alipay(HttpServletRequest request, HttpServletResponse response,Integer orderId) throws Exception{
        //获得初始化的AlipayClient
       AlipayClient alipayClient = new DefaultAlipayClient(SERVERURL,
                APP_ID, APP_PRIVATE_KEY,
                "json",
                CHARSET,
                ALIPAY_PUBLIC_KEY, "RSA2");
       ////创建API对应的request
        AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
        //支付成功之后跳转的地址(由于我们没有域名,我们使用natapp内网穿透工具)
        alipayRequest.setReturnUrl("http://5muhnf.natappfree.cc/pages/paySuccess.html");
        //支付成功通知地址
        alipayRequest.setNotifyUrl("http://5muhnf.natappfree.cc/pay/alipayNotifyNotice.do");
        Result mapResult = orderService.findByIdDetil(orderId);
        Map orderInfo = (Map) mapResult.getData();
        JSONObject json = new JSONObject();
        json.put("out_trade_no",outTradeNo(orderId));//商户订单号，需要保证不重复(支付回调会带上这个参数，我们可以用来查询对应的订单修改状态)
        json.put("total_amount",1000);//订单金额
        json.put("subject",orderInfo.get("setmeal"));//订单标题
        alipayRequest.setBizContent(json.toJSONString());

        String form="";
        try {
            form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
       response.setContentType("text/html;charset=" + CHARSET);
        response.getWriter().write(form);//直接将完整的表单html输出到页面
        response.getWriter().flush();
        response.getWriter().close();

    }
    /**
     * 生成商户订单号（年月日时分秒 + 订单号）
     * @param orderId
     * @return
     */
    private String outTradeNo(Integer orderId){
        String dateStr = DateUtil.format(new Date(), "yyyyMMddHHmmss");
        return dateStr + orderId;
    }
    /**
     * 支付宝通知我们支付状态，在这个接口里面可以修改订单支付的状态
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/alipayNotify")
    @ResponseBody
    public String alipayNotify(HttpServletRequest request, HttpServletRequest response) throws Exception {

        log.info("支付成功, 进入异步通知接口...");

        //获取支付宝POST过来反馈信息
        Map<String,String> params = new HashMap<String,String>();
        Map<String,String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用
//			valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        boolean signVerified = AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, "utf-8", "RSA2"); //调用SDK验证签名
        //——请在这里编写您的程序（以下代码仅作参考）——
		/* 实际验证过程建议商户务必添加以下校验：
		1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
		2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
		3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
		4、验证app_id是否为该商户本身。
		*/
        if(signVerified) {//验证成功
            //商户订单号
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");

            //支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");

            //交易状态
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");

            //付款金额
            String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8");

            if(trade_status.equals("TRADE_FINISHED")){
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //如果有做过处理，不执行商户的业务程序

                //注意： 尚自习的订单没有退款功能, 这个条件判断是进不来的, 所以此处不必写代码
                //退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
            }else if (trade_status.equals("TRADE_SUCCESS")){
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //如果有做过处理，不执行商户的业务程序

                //注意：
                //付款完成后，支付宝系统发送该交易状态通知

                // 修改叮当状态，改为 支付成功，已付款; 同时新增支付流水
            }
            log.info("支付成功...");
        }else {//验证失败
            log.info("支付, 验签失败...");
        }

        return "success";

}
}
